{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "import json\n",
    "from pprint import pprint\n",
    "\n",
    "from datasets import load_dataset\n",
    "from huggingface_hub import hf_hub_download\n",
    "import pandas as pd\n",
    "from dotenv import load_dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "import promptquality as pq\n",
    "from tqdm import tqdm\n",
    "tqdm.pandas()\n",
    "\n",
    "load_dotenv(\"../.env\")\n",
    "# pq.login(\"console.demo.rungalileo.io\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test with array properties:\n",
      "[{'description': 'Calculate distance between two points',\n",
      "  'properties': {'pointA': {'description': 'First point coordinates',\n",
      "                            'items': {'type': 'number'},\n",
      "                            'title': 'Pointa',\n",
      "                            'type': 'array'},\n",
      "                 'pointB': {'description': 'Second point coordinates',\n",
      "                            'items': {'type': 'number'},\n",
      "                            'title': 'Pointb',\n",
      "                            'type': 'array'}},\n",
      "  'required': ['pointA', 'pointB'],\n",
      "  'title': 'get_distance',\n",
      "  'type': 'object'}]\n"
     ]
    }
   ],
   "source": [
    "\n",
    "def get_bfcl_dataset(filename: str):\n",
    "    print(filename)\n",
    "    data_path = hf_hub_download(repo_id=\"gorilla-llm/Berkeley-Function-Calling-Leaderboard\", filename=filename, repo_type=\"dataset\")\n",
    "\n",
    "    def load_file(file_path: str):\n",
    "        result = []\n",
    "        with open(file_path) as f:\n",
    "            file = f.readlines()\n",
    "            for line in file:\n",
    "                result.append(json.loads(line))\n",
    "        return result\n",
    "\n",
    "    data = load_file(data_path)\n",
    "    df = pd.DataFrame.from_dict(data)\n",
    "    return df\n",
    "\n",
    "def get_bfcl_possible_answer(filename: str):\n",
    "    print(filename)\n",
    "    data_path = f\"../data/Berkeley-Function-Calling-Leaderboard/possible_answer/{filename}\"\n",
    "\n",
    "    def load_file(file_path: str):\n",
    "        result = []\n",
    "        with open(file_path) as f:\n",
    "            file = f.readlines()\n",
    "            for line in file:\n",
    "                result.append(json.loads(line))\n",
    "        return result\n",
    "\n",
    "    data = load_file(data_path)\n",
    "    return pd.DataFrame.from_dict(data)\n",
    "\n",
    "def update_conversations(conversation, ground_truth):\n",
    "    new_conv = []\n",
    "    for i, (conv, gt) in enumerate(zip(conversation, ground_truth)):\n",
    "        new_conv.append(conv[0])\n",
    "        # Only append ground truth if it's not the last element\n",
    "        if gt and i < len(conversation) - 1:\n",
    "            new_conv.append({\"role\": \"assistant\", \"content\": str(gt)})\n",
    "        elif not gt:\n",
    "            break     \n",
    "    return new_conv\n",
    "\n",
    "def convert_tools_to_langchain_format(tools):\n",
    "    \"\"\"\n",
    "    Convert from BFCL tool format to LangChain format.\n",
    "    \n",
    "    Args:\n",
    "        tools: Either a single tool dict or a list of tool dicts in BFCL format\n",
    "        \n",
    "    Returns:\n",
    "        Union[dict, list[dict]]: Tool(s) in LangChain format\n",
    "    \"\"\"\n",
    "    def convert_type(t):\n",
    "        \"\"\"Convert Python/BFCL types to JSON Schema types\"\"\"\n",
    "        type_mapping = {\n",
    "            \"float\": \"number\",\n",
    "            \"int\": \"integer\",\n",
    "            \"str\": \"string\",\n",
    "            \"bool\": \"boolean\",\n",
    "            \"dict\": \"object\",\n",
    "            \"list\": \"array\",\n",
    "            \"array\": \"array\",\n",
    "            \"decimal\": \"number\",\n",
    "            \"tuple\": \"array\",\n",
    "            \n",
    "            \"number\": \"number\",\n",
    "            \"integer\": \"integer\",\n",
    "            \"string\": \"string\",\n",
    "            \"boolean\": \"boolean\",\n",
    "            \"object\": \"object\"\n",
    "        }\n",
    "        return type_mapping.get(t.lower() if isinstance(t, str) else t, \"string\")\n",
    "    \n",
    "    def convert_property(property_dict):\n",
    "        \"\"\"Convert a single property with proper handling of array items\"\"\"\n",
    "        prop = {\n",
    "            \"description\": property_dict[\"description\"],\n",
    "            \"type\": convert_type(property_dict[\"type\"])\n",
    "        }\n",
    "        \n",
    "        # Handle array types\n",
    "        if prop[\"type\"] == \"array\":\n",
    "            # If items is explicitly defined, use it\n",
    "            if \"items\" in property_dict:\n",
    "                items_type = property_dict[\"items\"].get(\"type\", \"number\")\n",
    "                prop[\"items\"] = {\"type\": convert_type(items_type)}\n",
    "            else:\n",
    "                # Default to number type for arrays if not specified\n",
    "                prop[\"items\"] = {\"type\": \"number\"}\n",
    "                \n",
    "        return prop\n",
    "\n",
    "    def convert_single_tool(tool):\n",
    "        \"\"\"Convert a single tool from BFCL to LangChain format\"\"\"\n",
    "        properties = {}\n",
    "        \n",
    "        # Convert each property\n",
    "        for k, v in tool[\"parameters\"][\"properties\"].items():\n",
    "            prop = convert_property(v)\n",
    "            prop[\"title\"] = k.title()\n",
    "            properties[k] = prop\n",
    "\n",
    "        return {\n",
    "            \"description\": tool[\"description\"],\n",
    "            \"properties\": properties,\n",
    "            \"required\": tool[\"parameters\"].get(\"required\", []),\n",
    "            \"title\": tool[\"name\"],\n",
    "            \"type\": \"object\"\n",
    "        }\n",
    "    \n",
    "    # Handle both single tool and list of tools\n",
    "    if isinstance(tools, list):\n",
    "        return [convert_single_tool(tool) for tool in tools]\n",
    "    elif isinstance(tools, dict):\n",
    "        return convert_single_tool(tools)\n",
    "    else:\n",
    "        raise ValueError(\"Input must be either a single tool dict or a list of tool dicts\")\n",
    "\n",
    "# Test the conversion with array properties\n",
    "test_tools = [\n",
    "    {\n",
    "        \"description\": \"Calculate distance between two points\",\n",
    "        \"name\": \"get_distance\",\n",
    "        \"parameters\": {\n",
    "            \"properties\": {\n",
    "                \"pointA\": {\n",
    "                    \"description\": \"First point coordinates\",\n",
    "                    \"type\": \"array\"  # No items specified\n",
    "                },\n",
    "                \"pointB\": {\n",
    "                    \"description\": \"Second point coordinates\",\n",
    "                    \"type\": \"array\",\n",
    "                    \"items\": {\"type\": \"float\"}  # Items specified\n",
    "                }\n",
    "            },\n",
    "            \"required\": [\"pointA\", \"pointB\"],\n",
    "            \"type\": \"dict\"\n",
    "        }\n",
    "    }\n",
    "]\n",
    "\n",
    "# Run test\n",
    "print(\"Test with array properties:\")\n",
    "from pprint import pprint\n",
    "pprint(convert_tools_to_langchain_format(test_tools))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BFCL_v3_irrelevance.json\n",
      "BFCL_v3_irrelevance (100, 8)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>index</th>\n",
       "      <th>id</th>\n",
       "      <th>conversation</th>\n",
       "      <th>tools</th>\n",
       "      <th>tools_langchain</th>\n",
       "      <th>n_turns</th>\n",
       "      <th>len_query</th>\n",
       "      <th>n_tools</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>70</td>\n",
       "      <td>irrelevance_70</td>\n",
       "      <td>[{'role': 'user', 'content': 'Calculate the co...</td>\n",
       "      <td>[{'name': 'calculate_mortgage_payment', 'descr...</td>\n",
       "      <td>[{'description': 'Calculate the monthly mortga...</td>\n",
       "      <td>1</td>\n",
       "      <td>126</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>43</th>\n",
       "      <td>93</td>\n",
       "      <td>irrelevance_93</td>\n",
       "      <td>[{'role': 'user', 'content': 'What's the judge...</td>\n",
       "      <td>[{'name': 'law_firm.get_impactful_cases', 'des...</td>\n",
       "      <td>[{'description': 'Retrieve impactful cases han...</td>\n",
       "      <td>1</td>\n",
       "      <td>33</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>160</th>\n",
       "      <td>210</td>\n",
       "      <td>irrelevance_210</td>\n",
       "      <td>[{'role': 'user', 'content': 'Which place in P...</td>\n",
       "      <td>[{'name': 'recipe_based_restaurants', 'descrip...</td>\n",
       "      <td>[{'description': 'Search for the restaurants b...</td>\n",
       "      <td>1</td>\n",
       "      <td>41</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>115</th>\n",
       "      <td>165</td>\n",
       "      <td>irrelevance_165</td>\n",
       "      <td>[{'role': 'user', 'content': 'What type of ins...</td>\n",
       "      <td>[{'name': 'get_instrument_info', 'description'...</td>\n",
       "      <td>[{'description': 'Retrieves the details of a s...</td>\n",
       "      <td>1</td>\n",
       "      <td>35</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>152</th>\n",
       "      <td>202</td>\n",
       "      <td>irrelevance_202</td>\n",
       "      <td>[{'role': 'user', 'content': 'Who won the worl...</td>\n",
       "      <td>[{'name': 'game_score.calculate', 'description...</td>\n",
       "      <td>[{'description': 'Calculate the final game sco...</td>\n",
       "      <td>1</td>\n",
       "      <td>30</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>146</th>\n",
       "      <td>196</td>\n",
       "      <td>irrelevance_196</td>\n",
       "      <td>[{'role': 'user', 'content': 'What's the total...</td>\n",
       "      <td>[{'name': 'boardgame.calculate_score', 'descri...</td>\n",
       "      <td>[{'description': 'Calculate final scores for a...</td>\n",
       "      <td>1</td>\n",
       "      <td>65</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>76</td>\n",
       "      <td>irrelevance_76</td>\n",
       "      <td>[{'role': 'user', 'content': 'How do I get the...</td>\n",
       "      <td>[{'name': 'investment_trend_analysis', 'descri...</td>\n",
       "      <td>[{'description': 'Analyze the trend of a user'...</td>\n",
       "      <td>1</td>\n",
       "      <td>40</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>74</td>\n",
       "      <td>irrelevance_74</td>\n",
       "      <td>[{'role': 'user', 'content': 'What is the rate...</td>\n",
       "      <td>[{'name': 'investment_analysis.calculate_profi...</td>\n",
       "      <td>[{'description': 'Calculates the net profit gi...</td>\n",
       "      <td>1</td>\n",
       "      <td>90</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>141</th>\n",
       "      <td>191</td>\n",
       "      <td>irrelevance_191</td>\n",
       "      <td>[{'role': 'user', 'content': 'Who won the last...</td>\n",
       "      <td>[{'name': 'get_match_stats', 'description': 'R...</td>\n",
       "      <td>[{'description': 'Retrieve the match statistic...</td>\n",
       "      <td>1</td>\n",
       "      <td>39</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>84</th>\n",
       "      <td>134</td>\n",
       "      <td>irrelevance_134</td>\n",
       "      <td>[{'role': 'user', 'content': 'Who won the Worl...</td>\n",
       "      <td>[{'name': 'calculate_battle_outcome', 'descrip...</td>\n",
       "      <td>[{'description': 'Predicts the outcome of a hi...</td>\n",
       "      <td>1</td>\n",
       "      <td>27</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>100 rows × 8 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     index               id  \\\n",
       "20      70   irrelevance_70   \n",
       "43      93   irrelevance_93   \n",
       "160    210  irrelevance_210   \n",
       "115    165  irrelevance_165   \n",
       "152    202  irrelevance_202   \n",
       "..     ...              ...   \n",
       "146    196  irrelevance_196   \n",
       "26      76   irrelevance_76   \n",
       "24      74   irrelevance_74   \n",
       "141    191  irrelevance_191   \n",
       "84     134  irrelevance_134   \n",
       "\n",
       "                                          conversation  \\\n",
       "20   [{'role': 'user', 'content': 'Calculate the co...   \n",
       "43   [{'role': 'user', 'content': 'What's the judge...   \n",
       "160  [{'role': 'user', 'content': 'Which place in P...   \n",
       "115  [{'role': 'user', 'content': 'What type of ins...   \n",
       "152  [{'role': 'user', 'content': 'Who won the worl...   \n",
       "..                                                 ...   \n",
       "146  [{'role': 'user', 'content': 'What's the total...   \n",
       "26   [{'role': 'user', 'content': 'How do I get the...   \n",
       "24   [{'role': 'user', 'content': 'What is the rate...   \n",
       "141  [{'role': 'user', 'content': 'Who won the last...   \n",
       "84   [{'role': 'user', 'content': 'Who won the Worl...   \n",
       "\n",
       "                                                 tools  \\\n",
       "20   [{'name': 'calculate_mortgage_payment', 'descr...   \n",
       "43   [{'name': 'law_firm.get_impactful_cases', 'des...   \n",
       "160  [{'name': 'recipe_based_restaurants', 'descrip...   \n",
       "115  [{'name': 'get_instrument_info', 'description'...   \n",
       "152  [{'name': 'game_score.calculate', 'description...   \n",
       "..                                                 ...   \n",
       "146  [{'name': 'boardgame.calculate_score', 'descri...   \n",
       "26   [{'name': 'investment_trend_analysis', 'descri...   \n",
       "24   [{'name': 'investment_analysis.calculate_profi...   \n",
       "141  [{'name': 'get_match_stats', 'description': 'R...   \n",
       "84   [{'name': 'calculate_battle_outcome', 'descrip...   \n",
       "\n",
       "                                       tools_langchain  n_turns  len_query  \\\n",
       "20   [{'description': 'Calculate the monthly mortga...        1        126   \n",
       "43   [{'description': 'Retrieve impactful cases han...        1         33   \n",
       "160  [{'description': 'Search for the restaurants b...        1         41   \n",
       "115  [{'description': 'Retrieves the details of a s...        1         35   \n",
       "152  [{'description': 'Calculate the final game sco...        1         30   \n",
       "..                                                 ...      ...        ...   \n",
       "146  [{'description': 'Calculate final scores for a...        1         65   \n",
       "26   [{'description': 'Analyze the trend of a user'...        1         40   \n",
       "24   [{'description': 'Calculates the net profit gi...        1         90   \n",
       "141  [{'description': 'Retrieve the match statistic...        1         39   \n",
       "84   [{'description': 'Predicts the outcome of a hi...        1         27   \n",
       "\n",
       "     n_tools  \n",
       "20         1  \n",
       "43         1  \n",
       "160        1  \n",
       "115        1  \n",
       "152        1  \n",
       "..       ...  \n",
       "146        1  \n",
       "26         1  \n",
       "24         1  \n",
       "141        1  \n",
       "84         1  \n",
       "\n",
       "[100 rows x 8 columns]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "single_turn_filenames = [\n",
    "    # \"BFCL_v3_exec_simple.json\",\n",
    "    # \"BFCL_v3_exec_multiple.json\",\n",
    "    # \"BFCL_v3_exec_parallel.json\", \n",
    "    # \"BFCL_v3_exec_parallel_multiple.json\",\n",
    "    \"BFCL_v3_irrelevance.json\",\n",
    "    # \"BFCL_v3_chatable.json\",\n",
    "    # \"BFCL_v3_multiple.json\",\n",
    "    # \"BFCL_v3_parallel.json\", \n",
    "]\n",
    "\n",
    "multi_turn_filenames = [\n",
    "    \"BFCL_v3_multi_turn_base.json\", \n",
    "    \"BFCL_v3_multi_turn_long_context.json\", \n",
    "    \"BFCL_v3_multi_turn_miss_func.json\", \n",
    "    \"BFCL_v3_multi_turn_miss_param.json\",\n",
    "    \"BFCL_v3_multi_turn_composite.json\",  # Missing Parameters, Missing Functions, and Long-Context\n",
    "]\n",
    "\n",
    "filename = \"BFCL_v3_irrelevance.json\"\n",
    "df = get_bfcl_dataset(filename).iloc[50:].reset_index().drop([7, 78, 79, 99, 169, 188]).sample(100, random_state=42)\n",
    "df = df.rename(columns={\"function\": \"tools\"})\n",
    "\n",
    "\n",
    "def remove_dot_from_name(x): # langchain requirement\n",
    "    x[0]['title'] = x[0]['title'].replace(\".\", \"_\")\n",
    "    return x\n",
    "\n",
    "df[\"tools_langchain\"] = df[\"tools\"].apply(convert_tools_to_langchain_format)\n",
    "df[\"tools_langchain\"] = df[\"tools_langchain\"].apply(remove_dot_from_name)\n",
    "\n",
    "df = df.rename(columns={\"question\": \"conversation\"})\n",
    "df[\"conversation\"] = df.conversation.apply(lambda x: [x[0] for x in x if x])\n",
    "\n",
    "df[\"n_turns\"] = df.conversation.apply(lambda x: len(x))\n",
    "df[\"len_query\"] = df.conversation.apply(lambda x: len(x[-1][\"content\"]))\n",
    "df[\"n_tools\"] = df.tools.apply(lambda x: len(x))\n",
    "# df[\"n_function_calls\"] = df[\"involved_classes\"].apply(lambda x: len(x))\n",
    "\n",
    "name = os.path.splitext(filename)[0]\n",
    "print(name, df.shape)\n",
    "df.to_parquet(f\"../data/datasets/{name}.parquet\", engine=\"fastparquet\")\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['TradingBot', 'TicketAPI', 'VehicleControlAPI', 'MathAPI', 'MessageAPI', 'TravelAPI', 'TwitterAPI'])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "classes = [\n",
    " 'TradingBot',\n",
    " 'TicketAPI',\n",
    " 'VehicleControlAPI',\n",
    " 'MathAPI',\n",
    " 'MessageAPI',\n",
    " 'TravelAPI',\n",
    " 'TwitterAPI']\n",
    "\n",
    "files = ['trading_bot.json',\n",
    " 'ticket_api.json',\n",
    " 'vehicle_control.json',\n",
    " 'math_api.json',\n",
    " 'message_api.json',\n",
    " 'travel_booking.json',\n",
    " 'posting_api.json']\n",
    "\n",
    "basepath = \"../data/Berkeley-Function-Calling-Leaderboard/multi_turn_func_doc\"\n",
    "class_dict = {}\n",
    "\n",
    "for class_name, file in zip(classes, files):\n",
    "    filepath = os.path.join(basepath, file)\n",
    "    # read json lines file as a list of dictionaries\n",
    "    with open(filepath) as f:\n",
    "        data = [json.loads(line) for line in f]\n",
    "    class_dict[class_name] = data\n",
    "    \n",
    "class_dict.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BFCL_v3_multi_turn_base.json\n",
      "BFCL_v3_multi_turn_base.json\n",
      "BFCL_v3_multi_turn_base (150, 12)\n",
      "BFCL_v3_multi_turn_long_context.json\n",
      "BFCL_v3_multi_turn_long_context.json\n",
      "BFCL_v3_multi_turn_long_context (100, 12)\n",
      "BFCL_v3_multi_turn_miss_func.json\n",
      "BFCL_v3_multi_turn_miss_func.json\n",
      "BFCL_v3_multi_turn_miss_func (100, 13)\n",
      "BFCL_v3_multi_turn_miss_param.json\n",
      "BFCL_v3_multi_turn_miss_param.json\n",
      "BFCL_v3_multi_turn_miss_param (100, 12)\n",
      "BFCL_v3_multi_turn_composite.json\n",
      "BFCL_v3_multi_turn_composite.json\n",
      "BFCL_v3_multi_turn_composite (100, 13)\n"
     ]
    }
   ],
   "source": [
    "for filename in multi_turn_filenames:\n",
    "    if filename == \"BFCL_v3_multi_turn_base.json\":\n",
    "        samples = 150\n",
    "    else:\n",
    "        samples = 100\n",
    "    df = get_bfcl_dataset(filename).iloc[50:].sample(samples, random_state=42) # first fifty contain the gorilla file system\n",
    "    df_answer = get_bfcl_possible_answer(filename)\n",
    "    df = df.merge(df_answer, on=\"id\")\n",
    "    \n",
    "    # comprehension list to get the list of tools for each class\n",
    "    df[\"tools\"] = df.involved_classes.apply(lambda x: [class_dict[class_name] for class_name in x])\n",
    "    df[\"tools\"] = df.tools.apply(lambda x: [item for sublist in x for item in sublist])\n",
    "\n",
    "    # remove missed functions from tools\n",
    "    if \"missed_function\" in df.columns:\n",
    "        df[\"tools\"] = df.apply(lambda x: [tool for tool in x.tools if tool[\"name\"] not in list(x.missed_function.values())[0]], axis=1)\n",
    "\n",
    "    # convert tools to langchain format\n",
    "    df[\"tools_langchain\"] = df[\"tools\"].apply(convert_tools_to_langchain_format)\n",
    "    \n",
    "    df = df.rename(columns={\"question\": \"conversation\"})\n",
    "    # df[\"conversation\"] = df.conversation.apply(lambda x: [x[0] for x in x if x])\n",
    "    df[\"conversation\"] = df.apply(lambda x: update_conversations(x[\"conversation\"], x[\"ground_truth\"]), axis=1)\n",
    "    \n",
    "    df[\"n_turns\"] = df.conversation.apply(lambda x: len(x))\n",
    "    df[\"len_query\"] = df.conversation.apply(lambda x: len(x[-1][\"content\"]))\n",
    "    df[\"n_tools\"] = df.tools.apply(lambda x: len(x))\n",
    "    df[\"n_function_calls\"] = df[\"involved_classes\"].apply(lambda x: len(x))\n",
    "\n",
    "    name = os.path.splitext(filename)[0]\n",
    "    print(name, df.shape)\n",
    "    df.to_parquet(f\"../data/datasets/{name}.parquet\", engine=\"fastparquet\")\n",
    "\n",
    "# split the multi_turn_base dataset into single and multi function calls\n",
    "df = pd.read_parquet(\"../data/datasets/BFCL_v3_multi_turn_base.parquet\", engine=\"fastparquet\") \n",
    "name = \"BFCL_v3_multi_turn_base_single_func_call\"\n",
    "df[df.n_function_calls == 1].iloc[:50].to_parquet(f\"../data/datasets/{name}.parquet\", engine=\"fastparquet\")\n",
    "\n",
    "name = \"BFCL_v3_multi_turn_base_multi_func_call\"\n",
    "df[df.n_function_calls > 1].iloc[:50].to_parquet(f\"../data/datasets/{name}.parquet\", engine=\"fastparquet\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langgraph",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
